package com.yu.flow.demo;

import java.util.*;

public class WorkflowEngine {


    private TaskExecutor taskExecutor;

    public WorkflowEngine(TaskExecutor taskExecutor) {
        this.taskExecutor = taskExecutor;
    }

    public WorkflowContext executeWorkflow(WorkflowDefinition workflowDefinition, Map<String, Object> initialData) {
        WorkflowContext context = new WorkflowContext();

        // 设置初始数据
        if (initialData != null) {
            initialData.forEach(context::setData);
        }

        // 按拓扑排序执行任务
        executeTasksInOrder(workflowDefinition, context);

        return context;
    }

    private void executeTasksInOrder(WorkflowDefinition workflowDefinition, WorkflowContext context) {
        // 构建依赖图
        Map<String, TaskConfig> taskMap = new HashMap<>();
        Map<String, Set<String>> dependencies = new HashMap<>();
        Map<String, Set<String>> dependents = new HashMap<>();

        for (TaskConfig task : workflowDefinition.getTasks()) {
            taskMap.put(task.getName(), task);
            dependencies.put(task.getName(), new HashSet<>(task.getDependencies()));
            dependents.put(task.getName(), new HashSet<>());
        }

        // 构建依赖关系
        for (Map.Entry<String, Set<String>> entry : dependencies.entrySet()) {
            String taskName = entry.getKey();
            for (String dependency : entry.getValue()) {
                dependents.computeIfAbsent(dependency, k -> new HashSet<>()).add(taskName);
            }
        }

        // 找出所有没有前置依赖的任务
        Queue<String> readyTasks = new LinkedList<>();
        for (TaskConfig task : workflowDefinition.getTasks()) {
            if (task.getDependencies().isEmpty()) {
                readyTasks.add(task.getName());
            }
        }

        // 并行执行任务
        while (!readyTasks.isEmpty()) {
            String taskName = readyTasks.poll();
            TaskConfig taskConfig = taskMap.get(taskName);

            // 提交任务执行
            context.submitTask(taskName, () -> {
                System.out.println("Executing task: " + taskName);
                TaskResult<?> result = taskExecutor.execute(taskConfig, context);
                context.addTaskResult(taskName, result);

                // 检查依赖该任务的其他任务是否可以执行
                if (result.getStatus() == TaskStatus.SUCCESS || (result.getStatus() == TaskStatus.FAILED && taskConfig.isSkipOnFailure())) {
                    Set<String> dependentTasks = dependents.get(taskName);
                    if (dependentTasks != null) {
                        for (String dependentTask : dependentTasks) {
                            // 检查该依赖任务的所有前置条件是否都已满足
                            if (areDependenciesMet(dependentTask, dependencies, context)) {
                                readyTasks.add(dependentTask);
                            }
                        }
                    }
                }

                return result;
            });
        }

        // 等待所有任务完成
        context.waitForCompletion();
    }

    private boolean areDependenciesMet(String taskName, Map<String, Set<String>> dependencies, WorkflowContext context) {
        for (String dependency : dependencies.getOrDefault(taskName, Collections.emptySet())) {
            TaskResult<?> result = context.getTaskResult(dependency);
            if (result == null || result.getStatus() != TaskStatus.SUCCESS) {
                return false;
            }
        }
        return true;
    }
}